/**
 * 
 */
package auditoryUIbk;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

/**
 * @author sszhao
 *
 */
public class VisualMarkingPanel extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	//String[] COMPASS_8 = { "3", "4", "5", "6", "7", "0", "1", "2" };
	
	//String[] COMPASS_8 = { "Actor", "Cook", "Doctor", "Driver", "Farmer", "Hunter", "Lawyer", "Soldier" };
	
	String[] COMPASS_8 = {"", "", "", "", "", "", "", ""};
	
	private Dimension moPreferredSize = new Dimension(); 
	
	//double mdStartAngle = Math.toDegrees(Math.PI / 8.0 + Math.PI / 2.0);
	
	private int miSelectedIndex = -1; //initialize this value to -1 for now
	
	private Font moFont = new Font("name",1,1);
	
	private int miItemLimit = 8;
	
	/**
	 * @return the miSelectedIndex
	 */
	public int getSelectedIndex() {
		return miSelectedIndex;
	}

	/**
	 * @param miSelectedIndex the miSelectedIndex to set
	 */
	public void setSelectedIndex(int miSelectedIndex) {
		if(miSelectedIndex <0) this.miSelectedIndex = miSelectedIndex;
		else
			this.miSelectedIndex = this.translateIndex(miSelectedIndex);
		repaint();
	}

	/**
	 * @return the moPreferredSize
	 */
	public Dimension getPreferredSize() {
		return moPreferredSize;
	}

	/**
	 * @param moPreferredSize the moPreferredSize to set
	 */
	public void setPreferredSize(Dimension moPreferredSize) {
		this.moPreferredSize = moPreferredSize;
	}
	
	public void setPreferredSize(int width, int height){
		this.moPreferredSize.width = width;
		this.moPreferredSize.height = height;
	}
	
	/**
	 * Get the string values for the menu items
	 * @return
	 */
	public String[] getMenuItems(){
		return COMPASS_8;
	}
	
	//since the item mapping in the visual marking panel is not the same with the earPod, some translation is needed
	//to remap the items to the correct location. This variable is used by selected index, and drawing of the 
	//items. It's an important variable 
	int miInternalOffset = 0; //counter-clockwise
	
	/**
	 * set the menu items 
	 * @param data
	 */
	public void setMenuItems(String[] data){
		//check for empty conditions
		if(data!= null && data.length < miItemLimit) return;
		
		for(int i=0; i< miItemLimit; i++){
		//set the data to be displayed
			
			COMPASS_8[translateIndex(i)] = data[i];
		}
		repaint();
	}
	
	private int translateIndex(int oldIndex){
		int newIndex = oldIndex + miInternalOffset;
		if(newIndex > 8) newIndex -= miItemLimit;
		if(newIndex < 0) newIndex += miItemLimit;	
		return newIndex;
	}
	
	/**
	 * @return the moFont
	 */
	public Font getFont() {
		return moFont;
	}

	/**
	 * @param moFont the moFont to set
	 */
	public void setFont(Font moFont) {
		this.moFont = moFont;
	}
	
	int ShiftNorth(int p, int distance) {
		   return (p - distance);
    }

		int ShiftSouth(int p, int distance) {
		   return (p + distance);
		   }

		int ShiftEast(int p, int distance) {
		   return (p + distance);
		   }

		int ShiftWest(int p, int distance) {
		   return (p - distance);
		   }


	/**
	 * Draw the menus 
	 */
	public void paintComponent(Graphics gg){
		Graphics2D g = (Graphics2D) gg;
		g.setColor(Color.white);
		g.clearRect(0, 0, moPreferredSize.width, moPreferredSize.height);
		drawCompass8(new Point(moPreferredSize.width/2,moPreferredSize.height/2), moPreferredSize.width/5, 0, miSelectedIndex, g);
		//displayAllFonts(gg);
	}
	
	/**
	 * Draw the marking menu stuff. 
	 * @param center
	 * @param radius
	 * @param startAngle
	 * @param gg
	 * @param offset, the string position is all calculated based on the first item is located at the north position
	 *                but it might not match the system's position, so we might need to change it. 
	 */
	private void drawCompass8(Point center, int radius, double startAngle, int index, Graphics2D gg) {

		//Font font = new Font("TimesRoman", Font.BOLD, 24);
		//Font font = new Font("Verdana", Font.PLAIN, 24);

		/*if (dynamicFont) {

		 if (miScreenSize == 0)
		 font = new Font("SansSerif", Font.BOLD, 24);
		 else if (miScreenSize == 1) {
		 font = new Font("SansSerif", Font.BOLD, 14);
		 } else if (miScreenSize == 2) {
		 font = new Font("SansSerif", Font.BOLD, 8);
		 }
		 }*/
		
		FontMetrics fmetric = getFontMetrics(moFont);
		// current font metrics
		float width; // width is variable
		float height = fmetric.getHeight(); // height is constant

		int num = miItemLimit;
		Point[] points = new Point[num];
		Point[] fontPoints = new Point[num];
		double currentAngle = startAngle;
		double stepAngle = Math.PI / 4.0;
		
		for (int i = 0; i < num; i++) {
			
			//set the points for the drawing lines
			if(i == 2 || i==6){
				points[i] = new Point((int) (center.x + Math.cos(currentAngle)
					* radius), (int) (center.y + Math.sin(currentAngle)
					* radius));
			}
			else if(i == 0 || i== 4){
				points[i] = new Point((int) (center.x + Math.cos(currentAngle)
						* (radius*0.9)), (int) (center.y + Math.sin(currentAngle)
						* (radius*0.9)));
			}
			else {
				points[i] = new Point((int) (center.x + Math.cos(currentAngle)
						* (radius*0.6)), (int) (center.y + Math.sin(currentAngle)
						* (radius*0.6)));
			}
			
			currentAngle += stepAngle;
			
			//set the points for text
			width = fmetric.stringWidth(COMPASS_8[i]);
			fontPoints[i] = new Point(points[i]);
			//adjust the positions to the right position
			switch (i) {
			case 0: //e
				fontPoints[i].y = fontPoints[i].y + (int) (height/ 3.0f);
				break;
			case 1: //se
				fontPoints[i].y= fontPoints[i].y + (int) (height*2/ 3.0f);
				break;
			case 2: //s
				fontPoints[i].x = fontPoints[i].x - (int) (width / 2);
				fontPoints[i].y	= fontPoints[i].y + (int)(height / 2.0f);
				break;
			case 3: //sw
				fontPoints[i].x= (int) (fontPoints[i].x - width);
				fontPoints[i].y	=	fontPoints[i].y + (int)( height*2 / 3.0f);
				break;
			case 4: //w
				fontPoints[i].x= (int) (fontPoints[i].x - width); 
				fontPoints[i].y = fontPoints[i].y + (int)(height / 3.0f);
				break;
			case 5: //nw
				fontPoints[i].x = (int) (fontPoints[i].x - width);
					
				break;
			case 6: //n
				fontPoints[i].x = (int) (fontPoints[i].x - width / 2);
				break;
			case 7: //ne
				//same 
				break;
			}//end of switch
		}//end of for loop
		
		gg.setFont(moFont);
		
		drawLabels(COMPASS_8, (int) height, 4, 8, center.x, center.y, index, gg);
	}
	
	
	/**
	 * Draw the text with shadow
	 * @param t
	 * @param x
	 * @param y
	 * @param g
	 */
	public void drawShadowText(String t, int x, int y, Color foreColor, Graphics g){
		g.setColor(new Color(50, 50, 50));
		g.drawString(t, ShiftEast(x, 2), ShiftSouth(y, 2));
		//g.setColor(new Color(220, 220, 220));
		//g.setColor(backColor);
		g.setColor(foreColor);
		g.drawString(t, x, y);
	}
	
	private void drawLabels(String[] labels, int textHeight, int marginAroundText, int marginBetweenItems, int x0, int y0, int selectedIndex, Graphics2D g){
		
		FontMetrics fmetric = getFontMetrics(moFont);
		
		int heightOfItem = textHeight + 2*marginAroundText;
		double radius = 2 * (heightOfItem + marginBetweenItems);
		double radiusPrime = radius / Math.sqrt(2);
		
		for(int i=0; i< 8; i++){
			if(labels[i]!=null && labels[i].length()!=0){
				double theta =  (i* Math.PI/4.0 - Math.PI/2.0);
				double x = ((i%2)==0 ? radius: radiusPrime)*Math.cos(theta)+ x0;
				double y = ((i%2)==0 ? radius : radiusPrime)*Math.sin(theta)+y0;
				
				///now, try to make the shape look like a circule instead of liking a diamond 
				///here is how I am going to try it
				int xDelta = 15;
				switch(i){
				case 1:
				case 3:
					x += xDelta;
					break;
				case 5:
				case 7:
					x -= xDelta;
					break;
				}
				
				int stringWidth = fmetric.stringWidth(labels[i]);
				int widthOfItem = stringWidth + 2*marginAroundText;
				
				//We want items that appear side-by-side to have the same width,
				//so that the menu is symmetrical about a vertical axis. 
				if((i%4)!=0 && labels[8-i].length() != 0){
					int otherStringWidth = fmetric.stringWidth(labels[8-i]);
					if(otherStringWidth > stringWidth)
						widthOfItem = otherStringWidth + 2*marginAroundText;
					
				}//end of if((i%4)!=0
				
				if(1 <=i && i<=3){
					if(x - widthOfItem/2 <= x0 + marginBetweenItems){
						//item is too far to the left; shift it to the right
						x = x0 + marginBetweenItems + widthOfItem/2;
					}//end of inner if
				}//end of if(1 <= i
				else if(5 <= i && i <= 7){
					if(x + widthOfItem/2 >= x0 - marginBetweenItems){
						//item is too far to the right; shift it to the left
						x = x0 - marginBetweenItems -widthOfItem/2;
					}//end if inner if
				}//end of else 
				
				
					g.setColor(Color.LIGHT_GRAY);
					///time to draw the labels 
					g.drawRect((int) (x - widthOfItem/2), (int) (y - heightOfItem/2)+2, widthOfItem, heightOfItem);
				if(i == selectedIndex){
					g.setColor(new Color(184, 207, 229));
					g.fillRect((int) (x - widthOfItem/2), (int) (y - heightOfItem/2)+2, widthOfItem, heightOfItem);
				}
				
				g.setColor(Color.BLACK);
				g.drawString(labels[i], (int) (x - stringWidth/2), (int) (y + textHeight/2));
				
			}//end of if(labels
		}//end of for loop
	}//end of drawLabels method
	
	public static void main(String[] args){
		
		Dimension preferredSize = new Dimension(300, 300);
		
		VisualMarkingPanel panel = new VisualMarkingPanel();
		panel.setPreferredSize(preferredSize);
		JScrollPane scroll = new JScrollPane(panel);
		
		
		JFrame frame = new JFrame();
		
		frame.addWindowListener(new WindowAdapter() {
	        public void windowClosing(WindowEvent evt) {
	            // Exit the application
	            System.exit(0);
	        }
	    });
		
		frame.getContentPane().add(scroll);
	
		//frame.setSize(preferredSize);
		
		frame.setPreferredSize(preferredSize);
		frame.pack();
		frame.setVisible(true);
	}

	
	
}
